﻿#include "Server.h"


#define Check_JsonParse_body(request)\
					QJsonParseError error;\
					auto jdocument = QJsonDocument::fromJson(request.body(), &error);\
					if (error.error != QJsonParseError::NoError)\
					{\
						emit ApiData(QString("\t\t[%1] error:请求json数据失败;").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")));\
						qDebug() << "请求json数据失败;";\
						return Result::failure(ResultCode::ParamJsonInvalid);\
					}

#define Check_Query_Exec(query)\
						if (query.lastError().type() != QSqlError::NoError)\
						{\
							emit ApiData(QString("\t\t[%1] error:SQL语句执行失败;").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")));\
							qDebug() << "SQL语句执行失败;";\
							return Result::failure(ResultCode::ServerSqlQueryError);\
						}
					

//私有密钥：
const char* SECRET = "lifeilifei";

Server::Server()
{
	//开启服务器：
	m_server.listen(QHostAddress::Any, 8888);


	//添加路径丢失处理：
	m_server.setMissingHandler([=](const QHttpServerRequest& request, QHttpServerResponder&& responder)
		{
			QJsonObject jobject;
			jobject.insert("code", "3000");
			jobject.insert("messge", "不支持此操作");

			emit ApiData(QString("\t[%1] error:服务器并不支持此操作;").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")));

			responder.write(QJsonDocument(jobject));
		});


	//添加路由：
			//获取服务器版本：
	m_server.route("/api/version", [=](const QHttpServerRequest& request)
		{
			QJsonObject jobject;
			jobject.insert("version", "3.4.2");
			jobject.insert("name", "UserPrivilege_server");
			jobject.insert("datetime", QDateTime::currentDateTime().toString("yyyy-MM-dd"));
			jobject.insert("copyright", "zut_lifei_code");

			//发送Api数据:
			emit ApiData(QString("\t\t[%1] version:3.4.2;\n\t\tname:User_authority_managment_system-Server;\n\t\tdatetime:%2;\n\t\tcopyright:zut_lifei;")
				.arg(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss"))
				.arg(QDateTime::currentDateTime().toString("yyyy-MM-dd")));

			return QJsonDocument(jobject).toJson(QJsonDocument::Compact);
		});
			//用户登录：
	m_server.route("/api/login", [=](const QHttpServerRequest& request)
		{
			//检查body里的数据是否有错误：
			Check_JsonParse_body(request);


			//打开数据库线程池：
			SConnectionWarp warp;
			QSqlQuery query(warp.openConnection());

			query.prepare("select * from user where user_id=? and password=? and isDeleted=false limit 1;");
			query.bindValue(0, jdocument["user_id"].toString());
			query.bindValue(1, jdocument["password"].toString());
			if (!query.exec())
			{
				emit ApiData(QString("\t\t[%1] error:SQL语句执行失败").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")));
				//qDebug() << "SQL语句执行失败";

				return Result::failure(ResultCode::ServerSqlQueryError);
			}

			//是否查询到数据：
			if (!query.next())
			{
				emit ApiData(QString("\t\t[%1] error:帐号或密码不正确").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")));
				//qDebug() << "帐号或密码不正确";

				return Result::failure(ResultCode::UserLoginError);
			}

			//是否被禁用：
			if (!query.value("isEnable").toBool())
			{
				emit ApiData(QString("\t\t[%1] error:该帐户已被禁用").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")));
				//qDebug() << "该帐户已被禁用";

				return Result::failure(ResultCode::UserAccountIsEnable);
			}


			//生成token   使用jwt类来实现：
			QJsonObject playload =
			{
				{"user_id",jdocument["user_id"]},
				{"iat",QDateTime::currentDateTime().toString(Qt::DateFormat::ISODate)},
				{"exp",QDateTime::currentDateTime().addDays(18).toString(Qt::DateFormat::ISODate)}
			};
			SJwt::SJwtObject jwtObject(SJwt::SAlgorithm::HS256, playload, SECRET);

			//发送Api数据:
			emit ApiData(QString("\t[%1] success:有个瓜娃子进来老！").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")));
			//qDebug() << "还真有个User来了";

			//记录用户登录的访问量：
			m_total_interview_count++;

			return Result::success({ {"token",QString(jwtObject.jwt())} });
		});
			//用户注册：
	m_server.route("/api/register", [=](const QHttpServerRequest& request)
		{
			//检查body里的数据是否有错误：
			Check_JsonParse_body(request);


			//打开数据库线程池：
			SConnectionWarp warp;
			QSqlQuery query(warp.openConnection());

			query.prepare("insert ignore into user(user_id,username,password) value(?,?,?);");
			query.bindValue(0, jdocument["user_id"].toString());
			query.bindValue(1, jdocument["username"].toString());
			query.bindValue(2, jdocument["password"].toString());
			query.exec();

			//检查sql语句是否执行成功：
			Check_Query_Exec(query);


			//如果用户已存在：
			if (0 == query.numRowsAffected())
			{
				emit ApiData(QString("\t\t[%1] error:你注册的用户已经在屋里老;").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")));
				//qDebug() << "你注册的用户已经在屋里老;";

				return Result::failure(ResultCode::UserIdisExists);
			}

			
			//发送Api数据:
			emit ApiData(QString("\t\t[%1] success:%2:恭喜你，你已经被老子记住喽; ").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")).arg(jdocument["username"].toString()));
			//qDebug() << "还真有个User来了;";

			return Result::success();
		});
			//用户列表：
	m_server.route("/api/user/list", [=](const QHttpServerRequest& request)
		{
			//检查token是否有效：
			std::optional<QByteArray> retCheck = CheckToken(request);
			if (retCheck.has_value())
			{
				return retCheck.value();
			}


			auto uquery = request.query();
			auto user_id = uquery.queryItemValue("user_id");
			auto isEnable = uquery.queryItemValue("isEnable");
			auto page = uquery.queryItemValue("page").toInt();
			auto pageSize = uquery.queryItemValue("pageSize").toInt();
			auto request_query = uquery.queryItemValue("query");


			QString filter = "where isDeleted=false ";
			//两个相对互斥：
			if (!user_id.isEmpty())					//只通过用户id来查询
			{
				filter += QString("and user_id='%1' ").arg(user_id);
			}
			else if (!request_query.isEmpty())		//通过query语句来查询
			{
				filter += QString("and user_id like '%%1%' or username like '%%1%' or mobile like '%%1%' or email like '%%1%' ").arg(request_query);
			}
			if (!isEnable.isEmpty())
			{
				filter += QString("and isEnable=%1 ").arg(isEnable == "true" ? 1 : 0);
			}

			
			//开启数据库的线程池：
			SConnectionWarp warp;
			QSqlQuery query(warp.openConnection());

			//查询sql语句获取的查询的记录条数：
			query.exec(QString("select count(*) total from user %1;").arg(filter));
			//检查sql语句是否执行成功：
			Check_Query_Exec(query);
			query.next();
			int total = query.value("total").toInt();
			//qDebug() << "select total >" << total;

			//设置每页的记录条数：
			if (0 == pageSize)
			{
				pageSize = 20;
			}
			//qDebug() << "pageSize >" << pageSize;
			//获取当前总页数：
			int last_page = total / pageSize + (total %pageSize ? 0 : 1) + 1;
			if (page > last_page || page < 1)
			{
				page = 1;
			}


			//开始查询记录：
			QString sqlquery = "select user_id,username,gender,mobile,email,isEnable,password from user ";
			sqlquery += filter;
			sqlquery += QString("limit %1,%2;").arg((page - 1) * pageSize).arg(pageSize);
			query.exec(sqlquery);
			//emit ApiData(QString("\t\t\t[%1] %2").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")).arg(sqlquery));
			//qDebug() << sqlquery;
			//检查sql语句是否执行成功：
			Check_Query_Exec(query);


			QJsonObject jobject;
			//如果查询到的数据不为空，就把数据打包，发给客户端：
			if (query.size() > 0)
			{
				QJsonArray jArray;

				int count = query.record().count();
				qDebug() <<"需要转换的 sql的项个数为 >" << count;

				while (query.next())
				{
					jArray.append(Record_to_JsonObject(query.record()));
				}

				jobject.insert("lists", jArray);
				jobject.insert("cur_page", page);
				jobject.insert("pageSize", pageSize);
				jobject.insert("last_page",last_page);
				jobject.insert("total", total);
			}


			//发送Api数据:
			emit ApiData(QString("\t\t[%1] success:瓜娃子滴信息查询成功; ").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")));
			emit ApiData(QString("\t\t\t sqlquery >%1").arg(sqlquery));
			//qDebug() << "瓜娃子滴信息查询成功;";

			return Result::success(jobject);
		});
			//用户创建：
	m_server.route("/api/user/create", [=](const QHttpServerRequest& request)
		{
			//检查token是否有效:
			std::optional<QByteArray> retCheck = CheckToken(request);
			if (retCheck.has_value())
			{
				return retCheck.value();
			}

			//打印创建信息，方便查看错误：
			//qDebug() <<"打印创建信息，方便查看错误 >" << QString(request.body());
			//检查body里的数据是否有错误：
			Check_JsonParse_body(request);


			//检查必要的参数是否缺失：
			auto retObject = jdocument.object();
			if (	!(retObject.contains("user_id") && retObject.contains("username"))	)
			{
				emit ApiData(QString("\t\t[%1] error:你创建滴瓜娃子的名字或者编号是么得老;").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")));
				qDebug() << "你创建滴瓜娃子的名字或者编号是么得老;";

				return Result::failure(ResultCode::ParamJsonParameterMissing, "user_id 或者 username 参数是丢失的");
			}

			//如果没有填写密码，就设置默认密码：
			auto password = retObject.value("password").toString();
			if (password.isEmpty())
			{
				password = "123456";
			}


			//打开数据库线程池：
			SConnectionWarp warp;
			QSqlQuery query(warp.openConnection());

			query.prepare("insert ignore into user(user_id,username,gender,mobile,email,password) value(?,?,?,?,?,?);");
			query.bindValue(0, jdocument["user_id"].toString());
			query.bindValue(1, jdocument["username"].toString());
			query.bindValue(2, jdocument["gender"].toInteger());
			query.bindValue(3, jdocument["mobile"].toString());
			query.bindValue(4, jdocument["email"].toString());
			query.bindValue(5, password);
			query.exec();

			//检查sql语句是否执行成功：
			Check_Query_Exec(query);


			//如果影响的行数为0，那就表示么得插入成功：
			if (0 == query.numRowsAffected())
			{
				emit ApiData(QString("\t\t[%1] error:你创建的用户已经在屋里老;").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")));
				qDebug() << "你创建的用户已经在屋里老;";

				return Result::failure(ResultCode::UserIdisExists);
			}


			//发送Api数据:
			emit ApiData(QString("\t\t[%1] success:%2:恭喜你，你已经被老子记住喽; ").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")).arg(jdocument["username"].toString()));
			emit ApiData(QString("\t\t\t sqlquery >%1").arg(query.executedQuery()));
			//qDebug() << "还真有个User来了;";

			return Result::success();
		});
			//用户批量创建：
	m_server.route("/api/user/batch_create", [=](const QHttpServerRequest& request)
		{
			//检查token是否有效:
			std::optional<QByteArray> retCheck = CheckToken(request);
			if (retCheck.has_value())
			{
				return retCheck.value();
			}

			//检查body里的数据是否有错误：
			Check_JsonParse_body(request);


			//打开数据库线程池：
			SConnectionWarp warp;
			auto db = warp.openConnection();
			QSqlQuery query(db);

			db.transaction();			//开启事务；来处理可能大量的数据；
			query.prepare("insert into user(user_id,username,gender,mobile,email,password) values(?,?,?,?,?,?);");

			auto RootObject = jdocument.object();
			auto jArray = RootObject.value("lists").toArray();
			//qDebug() << "批量创建的用户的数量 >" << jArray.size();

			//遍历装有多个用户数据的数组，开始逐个插入到数据库：
			for (int i = 0; i < jArray.size(); i++)
			{
				auto retObject = jArray.at(i).toObject();

				//检查必要的参数是否缺失：
				if (!(retObject.contains("user_id") && retObject.contains("username")))
				{
					db.rollback();				//如果在插入过程中发生任何错误，就会回滚事务并返回失败的结果

					emit ApiData(QString("\t\t[%1] error:在你的多个用户数据中有一个滴瓜娃子的名字或者编号是么得老,回滚事务并返回失败的结果;").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")));
					qDebug() << "在你的多个用户数据中有一个滴瓜娃子的名字或者编号是么得老,回滚事务并返回失败的结果;";

					return Result::failure(ResultCode::ParamJsonParameterMissing, "user_id 或者 username 参数是丢失的");
				}

				//插入数据：
				query.bindValue(0, retObject.value("user_id").toString());
				query.bindValue(1, retObject.value("username").toString());
				query.bindValue(2, retObject.value("gender").toInteger());
				query.bindValue(3, retObject.value("mobile").toString());
				query.bindValue(4, retObject.value("email").toString());
				query.bindValue(5, retObject.value("password").toString());

				//Sql语句执行失败判断：
				if (!query.exec())
				{
					db.rollback();				//如果在插入过程中发生任何错误，就会回滚事务并返回失败的结果

					emit ApiData(QString("\t\t[%1] error:在你的多个用户数据中有一个滴瓜娃子(%2)没有插入成功老,SQL语句执行失败,回滚事务并返回失败的结果;")
						.arg(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss"))
						.arg(jdocument["username"].toString()));
					//qDebug() << "在你的多个用户数据中有一个滴瓜娃子没有插入成功老,SQL语句执行失败,回滚事务并返回失败的结果;";

					return Result::failure(ResultCode::ServerSqlQueryError,query.lastError().text());
				}
			}
			db.commit();				//将事务中的操作永久保存到数据库中

			
			//如果影响的行数为0，那就表示么得插入成功：
			if (0 == query.numRowsAffected())
			{
				emit ApiData(QString("\t\t[%1] error:你创建的这些用户都已经在屋里老;").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")));
				qDebug() << "你创建的这些用户都已经在屋里老;";

				return Result::failure(ResultCode::UserIdisExists);
			}


			//发送Api数据:
			emit ApiData(QString("\t\t[%1] success:%2:恭喜你们，你们哈搓搓已经被老子记住喽; ").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")).arg(jdocument["username"].toString()));
			//qDebug() << "有一帮哈搓搓来了;";

			return Result::success();
		});
			//用户删除：
	m_server.route("/api/user/delete", [=](const QHttpServerRequest& request)
		{
			//检查token是否有效:
			std::optional<QByteArray> retCheck = CheckToken(request);
			if (retCheck.has_value())
			{
				return retCheck.value();
			}

			//检查body里的数据是否有错误：
			Check_JsonParse_body(request);


			//检查必要的参数是否缺失：
			auto jArray = jdocument["user_id_lists"].toArray();
			if (jArray.isEmpty())
			{
				emit ApiData(QString("\t\t[%1] 想要删除的用户都删除干净老;").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")));
				qDebug() << "想要删除的用户都删除干净老;";

				return Result::success();
			}

			//打开数据库线程池：
			SConnectionWarp warp;
			QSqlQuery query(warp.openConnection());

			query.prepare("update user set isDeleted=true where user_id=?;");
			//qDebug() << "sql要删除的用户数量 >" << jArray.size();
			for (int i = 0; i < jArray.size(); i++)
			{
				query.bindValue(0, jArray.at(i).toString());
				query.exec();

				//检查sql语句是否执行成功：
				Check_Query_Exec(query);

				emit ApiData(QString("\t\t\t sqlquery >%1").arg(query.lastQuery()));
			}
		

			//发送Api数据:
			emit ApiData(QString("\t\t[%1] success:该用户删除成功老;").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")));
			//qDebug() << "该用户删除成功老;";

			return Result::success();
		});
			//用户修改：
	m_server.route("/api/user/modify", [=](const QHttpServerRequest& request)
		{
			//检查token是否有效:
			std::optional<QByteArray> retCheck = CheckToken(request);
			if (retCheck.has_value())
			{
				return retCheck.value();
			}

			/*
				修改操作是：通过query里的数据的用户id来确认要修改的用户目标，body里的数据是将要修改的用户的数据信息;
			*/


			auto request_query = request.query();
			//确定query数据是否存在：
			if (!request_query.hasQueryItem("user_id"))
			{
				emit ApiData(QString("\t\t[%1] error:在修改操作中，请求的数据（query）缺少参数（用户的id）;").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")));
				//qDebug() << "在修改操作中，请求的数据（query）缺少参数（用户的id）;";

				return Result::failure(ResultCode::ParamJsonParameterMissing);
			}

			//检查body里的数据是否有错误：
			Check_JsonParse_body(request);

			
			//拼接sql更新语句：
			QString updatesqlquery;
			auto jObject = jdocument.object();
			if (jObject.contains("username"))
			{
				updatesqlquery += QString("username='%1' ,").arg(jObject.value("username").toString());
			}
			if (jObject.contains("gender"))
			{
				updatesqlquery += QString("gender=%1 ,").arg(jObject.value("gender").toInt());
			}
			if (jObject.contains("mobile"))
			{
				updatesqlquery += QString("mobile='%1' ,").arg(jObject.value("mobile").toString());
			}
			if (jObject.contains("email"))
			{
				updatesqlquery += QString("email='%1' ,").arg(jObject.value("email").toString());
			}
			if (jObject.contains("isEnable"))
			{
				updatesqlquery += QString("isEnable=%1 ,").arg(jObject.value("isEnable").toInt());
			}
			if (jObject.contains("isDeleted"))
			{
				updatesqlquery += QString("isDeleted=%1 ,").arg(jObject.value("isDeleted").toInt());
			}
			if (jObject.contains("password"))
			{
				updatesqlquery += QString("password='%1' ,").arg(jObject.value("password").toString());
			}
			updatesqlquery.chop(1);					//截断字符串中最后一个逗号；


			//打开数据库线程池：
			SConnectionWarp warp;
			QSqlQuery query(warp.openConnection());
			QString sql = QString("update user set %1 where user_id='%2'; ").arg(updatesqlquery).arg(request_query.queryItemValue("user_id"));
			query.exec(sql);
			QLOG_DEBUG() << query.lastQuery();			//将		最后一次查询的 SQL 语句的字符串	输出到一个调试日志中

			//检查sql语句是否执行成功：
			Check_Query_Exec(query);


			//如果sql语句的影响行数为0，则表示修改失败：
			if (0 == query.numRowsAffected())
			{
				emit ApiData(QString("\t\t[%1] error:应该是修改成功老，但是没得数据被修改;").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")));
				emit ApiData(QString("\t\t\t sqlquery >%1").arg(sql));
				//qDebug() << "应该是修改成功老，但是没得数据被修改;";

				return Result::success(ResultCode::SuccessButNotData);
			}


			//发送Api数据:
			emit ApiData(QString("\t\t[%1] success:用户的数据修改成功老;").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")));
			emit ApiData(QString("\t\t\t sqlquery >%1").arg(sql));
			//qDebug() << "用户的数据修改成功老;";

			return Result::success();
		});
			//用户批量修改：
	m_server.route("/api/user/batch_modify", [=](const QHttpServerRequest& request)
		{
			//检查token是否有效:
			std::optional<QByteArray> retCheck = CheckToken(request);
			if (retCheck.has_value())
			{
				return retCheck.value();
			}


			//检查body里的数据是否有错误：
			Check_JsonParse_body(request);

			auto jArray = jdocument["lists"].toArray();
			if (jArray.isEmpty())
			{
				emit ApiData(QString("\t\t[%1] error:搞毛啊，一个要修改的没有，哈搓搓;").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")));
				//qDebug() << "搞毛啊，一个要修改的没有，哈搓搓;";

				return Result::failure(ResultCode::SuccessButNotData);
			}


			//拼接sql更新语句：
			QString updatesqlquery;
			for (int i = 0; i < jArray.size(); i++)
			{
				auto jObject = jArray.at(i).toObject();

				auto conditionObject = jObject.value("condition").toObject();
				auto updateObject = jObject.value("update").toObject();

				//拼接条件语句：
				QString condition;
				for (auto it = conditionObject.begin(); it != conditionObject.end(); it++)
				{
					if (it.key() == "user_id")
					{
						condition += QString(" user_id='%1' and").arg(it.value().toString());
					}
					else if (it.key() == "isEnable")
					{
						condition += QString(" isEnable=%1 and").arg(it.value().toInt());
					}
					else if (it.key() == "isDeleted")
					{
						condition += QString(" isDeleted='%1' and").arg(it.value().toInt());
					}
				}
				condition.chop(3);			//截断条件字符串中的后三个字段，也就是and

				//拼接更新语句：
				QString update;
				for (auto it = updateObject.begin(); it != updateObject.end(); it++)
				{
					if (it.key() == "username")
					{
						update += QString("username='%1' ,").arg(it.value().toString());
					}
					if (it.key() == "password")
					{
						update += QString("password='%1' ,").arg(it.value().toString());
					}
					if (it.key() == "mobile")
					{
						update += QString("mobile='%1' ,").arg(it.value().toString());
					}
					if (it.key() == "email")
					{
						update += QString("email='%1' ,").arg(it.value().toString());
					}
					if (it.key() == "isEnable")
					{
						update += QString("isEnable=%1 ,").arg(it.value().toBool());
					}
					if (it.key() == "isDeleted")
					{
						update += QString("isDeleted=%1 ,").arg(it.value().toBool());
					}
				}
				update.chop(1);				//截断最后一个逗号

				auto sqlquery = QString("update user set %1  where %2;").arg(update).arg(condition);
				updatesqlquery.append(sqlquery);
			}

			QLOG_DEBUG() << updatesqlquery;


			//打开数据库线程池：
			SConnectionWarp warp;
			QSqlQuery query(warp.openConnection());
			query.exec(updatesqlquery);

			//检查sql语句是否执行成功：
			Check_Query_Exec(query);
			//qDebug() << "query >" << updatesqlquery;


			//如果sql语句的影响行数为0，则表示修改失败：
			if (0 == query.numRowsAffected())
			{
				emit ApiData(QString("\t\t[%1] error:应该是修改成功老，但是没得数据被修改;").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")));
				emit ApiData(QString("\t\t\t sqlquery >%1").arg(updatesqlquery));
				//qDebug() << "应该是修改成功老，但是没得数据被修改;";

				return Result::success(ResultCode::SuccessButNotData);
			}


			//发送Api数据:
			emit ApiData(QString("\t\t[%1] success:用户的数据都修改成功老;").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")));
			emit ApiData(QString("\t\t\t sqlquery >%1").arg(updatesqlquery));
			//qDebug() << "用户的数据都修改成功老;";

			return Result::success();
		});
			//用户头像上传（修改） POST:
	m_server.route("/api/user/avatar", QHttpServerRequest::Method::Post, [=](const QHttpServerRequest& request)
		{
			std::optional<QByteArray> retCheck = CheckToken(request);
			if (retCheck.has_value())
			{
				return retCheck.value();
			}


			/*
				头像的上传是：通过query里面的数据的用户id来确认上传的目标；body里面的数据是该目标要上传的头像的信息和数据；
			*/


			auto request_query = request.query();
			//确认query数据是否存在：
			if (!request_query.hasQueryItem("user_id"))
			{
				emit ApiData(QString("\t\t[%1] error:在上传头像的操作中，请求的数据（query）缺少参数（用户的id）;").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")));
				//qDebug() << " 在上传头像的操作中，请求的数据（query）缺少参数（用户的id）;";

				return Result::failure(ResultCode::ParamJsonParameterMissing);
			}
			//获取query中的用户id：
			auto user_id = request_query.queryItemValue("user_id");

			//获取body中的头像数据：
			auto avatar_data = request.body();

			//解析body中的form-data数据（头像数据）：
			HttpPartParse parse(avatar_data);
			if (!parse.parse())
			{
				emit ApiData(QString("\t\t[%1] error:头像数据(body --- form-data)参数解析错误老").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")));
				//qDebug() << "头像数据(body --- form-data)参数解析错误老";

				return Result::failure(ResultCode::ParamParseError);
			}
			//qDebug() << "body中解析出来的 avatar data > parseName:" << parse.parameterName() << " parseFileName:" << parse.fileName();

			//创建头像文件的保存路径：
			auto path = "images/avatar/";
			QDir dir;
			//创建路径：
			if (!dir.exists(path))
			{
				dir.mkpath(path);
			}
			QFile file(path + user_id + "." + QFileInfo(parse.fileName()).suffix());
			//创建和写入头像数据的文件:
			if (!file.open(QIODevice::WriteOnly))
			{
				emit ApiData(QString("\t\t[%1] error:头像数据的文件保存失败老，可能是文件权限不能写入;").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")));
				//qDebug() << "头像数据的文件保存失败老，可能是文件权限不能写入;";

				return Result::failure(ResultCode::ServerInnerError, "文件保存失败老");
			}
			file.write(parse.fileData());
			file.close();


			//打开数据库线程池：
			SConnectionWarp warp;
			QSqlQuery query(warp.openConnection());

			query.prepare("update user set avatar_path=? where user_id=? and isDeleted=false;");
			query.bindValue(0, file.fileName());
			query.bindValue(1, user_id);
			query.exec();

			//检查sql语句是否执行成功：
			Check_Query_Exec(query);


			emit ApiData(QString("\t\t[%1] success:(%2)该用户头像文件上传成功老;").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")).arg(user_id));
			emit ApiData(QString("\t\t\t sqlquery >%1").arg(query.executedQuery()));
			//qDebug() << "该用户头像文件上传成功老;";

			return Result::success();
		});
			//用户头像获取（下载） GET:
	m_server.route("/api/user/avatar", QHttpServerRequest::Method::Get, [=](const  QHttpServerRequest& request,QHttpServerResponder&& responder)
		{
			std::optional<QByteArray> retCheck = CheckToken(request);
			if (retCheck.has_value())
			{
				responder.write(retCheck.value(),"applicaiton/json");
				return;
			}


			/*
				头像的下载也是：通过query里面的数据的用户id来确认要被下载的目标；body里面的数据是该目标要上传的头像的信息和数据；
			*/


			auto request_query = request.query();
			//确认query数据是否存在：
			if (!request_query.hasQueryItem("user_id"))
			{
				emit ApiData(QString("\t\t[%1] error:在下载头像的操作中，请求的数据（query）缺少参数（用户的id）;").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")));
				//qDebug() << " 在下载头像的操作中，请求的数据（query）缺少参数（用户的id）;";

				responder.write(ResultCode::ParamJsonParameterMissing.toJson(), "application/json");
				return;
			}
			//获取query中的用户id：
			auto user_id = request_query.queryItemValue("user_id");

		
			//打开数据库线程池：
			SConnectionWarp warp;
			QSqlQuery query(warp.openConnection());

			query.prepare("select avatar_path from user where user_id=? and isDeleted=false");
			query.bindValue(0, user_id);
			if (!query.exec())
			{
				emit ApiData(QString("\t\t[%1] error:在下载头像的操作中，SQL语句执行失败老,错误信息:%2;").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")).arg(query.lastError().text()));
				//qDebug() << " 在下载头像的操作中，SQL语句执行失败老;";

				responder.write(ResultCode::ServerSqlQueryError.toJson(), "application/json");
				return;
			}
			if (!query.next())
			{
				emit ApiData(QString("\t\t[%1] error:在下载头像的操作中，请求的数据失败老，错误信息:%2;").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")).arg(query.lastError().text()));
				//qDebug() << " 在下载头像的操作中，请求的数据失败老;";

				responder.write(ResultCode::SuccessButNotData.toJson(), "application/json");
				return;
			}


			QFile file(query.value("avatar_path").toString());
			if (!file.open(QIODevice::ReadOnly))
			{
				emit ApiData(QString("\t\t[%1] error:在下载头像的操作中，么得找到头像;").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")));
				//qDebug() << " 在下载头像的操作中，么得找到头像;";

				responder.write(Result::failure(ResultCode::ServerResourceNotFound,"头像未找到"), "application/json");
				return;
			}


			responder.writeStatusLine();
			responder.writeHeader("Content-Type", QString("image/%1").arg(QFileInfo(file.fileName()).suffix()).toUtf8());
			responder.writeHeader("Content-Length", QByteArray::number(file.size()));
			responder.writeHeader("Content-Disposition", ("attachment;filename=" + QFileInfo(file.fileName()).fileName()).toUtf8());
			
			emit ApiData(QString("\t\t[%1] success:(%2)该用户头像文件下载成功老;").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")).arg(user_id));
			emit ApiData(QString("\t\t\t sqlquery >%1").arg(query.lastQuery()));
			//qDebug() << "该用户头像文件下载成功老;";
			
			responder.writeBody(file.readAll());
		});


	//布局初始化：
	Layoutinit();
}

std::optional<QByteArray> Server::CheckToken(const QHttpServerRequest& request)
{
	//校验token：
	auto auth = request.value("Authorization");
	if (auth.isEmpty())										//如果没有认证头
	{
		emit ApiData(QString("\t\t[%1] Authorization”帐号未授权;").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")));
		qDebug() << "Authorization”帐号未授权;";

		return Result::failure(ResultCode::UserUnauthorized);
	}

	//必须以Bearer 开头：
	if (!auth.startsWith("Bearer"))
	{
		emit ApiData(QString("\t\t[%1] 账号授权格式错误，只支持使用承载方式Bearer;").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")));
		qDebug() << "账号授权格式错误，只支持使用承载方式Bearer;";

		return Result::failure(ResultCode::UserAuthorizationFormatError);
	}

	//拿到token：
	auto token = auth.mid(strlen("Bearer"));
	qDebug() <<"token >" << token;
	//再验证token：
	auto jwtObject = SJwt::SJwtObject::decode(token, SJwt::SAlgorithm::HS256, SECRET);
	if (jwtObject.status() == SJwt::SJwtObject::Status::Expired)
	{
		emit ApiData(QString("\t\t[%1] 令牌的帐户(token)格式已过期;").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")));
		qDebug() << "令牌的帐户(token)格式已过期";

		return Result::failure(ResultCode::UserTokenExpired);
	}
	if (!jwtObject.isValid())
	{
		emit ApiData(QString("\t\t[%1] 帐户令牌(token)格式无效;").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")));
		qDebug() << "帐户令牌(token)格式无效";

		return Result::failure(ResultCode::UserTokenInvalid);
	}


	return {};
}

QJsonObject Server::Record_to_JsonObject(const QSqlRecord& record)
{
	QJsonObject juser;

	for (size_t i = 0; i < record.count(); i++)
	{
		const auto& object_key = record.fieldName(i);
		const auto& object_value = record.value(i);
		switch (object_value.typeId())
		{
			case QMetaType::Bool:
				juser.insert(object_key, object_value.toBool());
				break;
			case QMetaType::Int:
			case QMetaType::UInt:
			case QMetaType::LongLong:
			case QMetaType::ULongLong:
			case QMetaType::Long:
			case QMetaType::Short:
			case QMetaType::ULong:
			case QMetaType::UShort:
				juser.insert(object_key, object_value.toLongLong());
				break;
			case QMetaType::Double:
			case QMetaType::Float:
				juser.insert(object_key, object_value.toDouble());
				break;
			default:
				juser.insert(object_key, object_value.toString());
				break;
		}
	}

	return juser;
}


void Server::Layoutinit()
{
	this->setStyleSheet("background-color:rgb(33,33,33);color:white");
	this->setWindowTitle("User_authority_management_system-Server");
	this->setWindowIcon(QIcon(":/Serverimages/a.ico"));
	this->resize(1039,520);


	//整体布局：
	m_total_layout = new QHBoxLayout(this);


	//侧边状态栏：
	m_navigation_layout = new QVBoxLayout;
			//状态栏标题：
	m_titleLab = new QLabel("User管理系统Server");
	m_titleLab->setStyleSheet("font:bold 13px;color:rgb(195,232,141)");
	m_navigation_layout->addWidget(m_titleLab);
			//添加间隔：
	m_navigation_layout->addSpacerItem(new QSpacerItem(1, 30));
			//状态视图：
	m_navigation_view = new QListView;
	m_navigation_model = new QStandardItemModel;
	m_navigation_view->setStyleSheet("border:none;color:rgb(220,220,170);");
	m_navigation_view->setModel(m_navigation_model);
	m_navigation_view->setEditTriggers(QListView::NoEditTriggers);								//禁止编辑
	m_navigation_view->setSelectionMode(QListView::SelectionMode::ContiguousSelection);			//设置行选择
	m_navigation_view->setSelectionMode(QAbstractItemView::NoSelection);					//设置不可选中
	m_navigation_view->setFocusPolicy(Qt::NoFocus);										//取消焦点
	m_navigation_layout->addWidget(m_navigation_view);
	//添加到整体布局中：
	m_total_layout->addLayout(m_navigation_layout,2);


	//数据显示视图：
	m_data_view = new QListView;
	m_data_model = new QStandardItemModel;
	m_data_view->setModel(m_data_model);
	m_data_view->setEditTriggers(QListView::NoEditTriggers);									//禁止编辑
	m_data_view->setSelectionMode(QListView::SelectionMode::ContiguousSelection);				//设置行选择
	m_data_view->setSelectionMode(QAbstractItemView::NoSelection);							//设置不可选中
	m_data_view->setFocusPolicy(Qt::NoFocus);										//取消焦点
	m_data_view->setStyleSheet("border:none;");
	//添加到整体布局中：
	m_total_layout->addWidget(m_data_view,8);


	//信号槽初始化：
	Connectinit();
}

void Server::Connectinit()
{
	Update_navigation_view();

	Update_data_view();

	//状态栏信息接收：
	connect(SSqlconnectionPool::instance(), &SSqlconnectionPool::SqlData, this, &Server::Update_navigation_view);

	
	//数据显示信息接收：
	connect(this, &Server::ApiData, this, &Server::Update_data_view);
}

void Server::Update_navigation_view(QString data)
{
	//先清空模型中的数据：
	m_navigation_model->clear();




	m_navigation_model->appendRow(new QStandardItem("the UseConnections is >"));
	//使用量：
	QString use_count = data.mid(data.indexOf("use>") + strlen("use>"), 1);
	QStandardItem* item = new QStandardItem(data == "0" ? "0" : use_count);
	item->setData(QColor(195, 232, 141),Qt::ForegroundRole);
	item->setTextAlignment(Qt::AlignRight);
	m_navigation_model->appendRow(item);


	m_navigation_model->appendRow(new QStandardItem("the UnuseConnections is >"));
	//未使用量：
	QString unuse_count = data.mid(data.indexOf("unuse>") + strlen("unuse>"),1);
	item = new QStandardItem(data == "0" ? "0" : unuse_count);
	item->setData(QColor(195, 232, 141), Qt::ForegroundRole);
	item->setTextAlignment(Qt::AlignRight);
	m_navigation_model->appendRow(item);


	m_navigation_model->appendRow(new QStandardItem("the TotalConnections is >"));
	//总量：
	QString total_count = data.mid(data.indexOf("total>") + strlen("total>"),1);
	item = new QStandardItem(data == "0" ? "0" : total_count);
	item->setData(QColor(195, 232, 141), Qt::ForegroundRole);
	item->setTextAlignment(Qt::AlignRight);
	m_navigation_model->appendRow(item);


	m_navigation_model->appendRow(new QStandardItem("总访问量 >"));
	//总访问量：
	item = new QStandardItem(QString::number(m_total_interview_count));
	item->setData(QColor(195, 232, 141), Qt::ForegroundRole);
	item->setTextAlignment(Qt::AlignRight);
	m_navigation_model->appendRow(item);

}

void Server::Update_data_view(QString data)
{
	//如果客户端是二次登录，那么服务器的显示版本信息就不用再显示了，而且把data重置成 "" 还能起到两次登录的间隔效果，方便查看操作信息：
	if (1 >= m_total_interview_count && data.contains("version"))
	{
		data = "";
	}


	QStandardItem* item = new QStandardItem(data);

	//按数据情况设置字体的颜色：
	if (data.contains("网络网址已成功连接老!"))
	{
		item->setData(QColor(255, 180, 0),Qt::ForegroundRole);
	}
	else if (data.contains("有个瓜娃子进来老！"))
	{
		item->setData(QColor(156, 220, 254), Qt::ForegroundRole);
	}
	else if (data.contains("version") && 0 == m_total_interview_count)
	{
		item->setData(QColor(247, 140, 108), Qt::ForegroundRole);
	}
	else if(data.contains("error"))
	{
		item->setData(QColor(227, 52, 28), Qt::ForegroundRole);
	}
	else if (data.contains("success"))
	{
		item->setData(QColor(117, 250, 97), Qt::ForegroundRole);
	}
	else if (data.contains("sqlquery >"))
	{
		item->setData(QColor(164, 189, 143), Qt::ForegroundRole);
	}

	m_data_model->appendRow(item);


	//将视图滚动到最下边：
	m_data_view->scrollToBottom();
}

